//This file contains the body parser middleware.
import 'dart:async';
import 'dart:convert';
import 'dart:io';

import 'package:simple_server/src/context.dart';
import 'package:simple_server/src/log.dart';
import 'package:simple_server/src/middleware/middleware.dart';

class BodyParserMiddleware<T extends Context> extends Middleware<T> {
  final _parseMethods = <String>{'post', 'put'};

  final _ignorePaths = <String>{};

  ///Ignore body parser for the specified path.
  ///ignored paths will not parse the request body.need process request body manually.
  void ignoreParseBody(String path) => _ignorePaths.add(path);

  @override
  Future<void> call(T context, Next next) async {
    try {
      if (!_parseMethods.contains(context.method)) return;
      if (_ignorePaths.any((e) => context.path.startsWith(e))) return;
      await bodyParse(context);
    } catch (e, s) {
      error(e, s, 'bodyParserMiddleware');
    } finally {
      await next();
    }
  }
}

Future<void> bodyParse<T extends Context>(T context) async {
  final body = await utf8.decoder.bind(context.request).join();
  if (body.isEmpty) return;
  context['body'] = body;
  final header = context.headers[HttpHeaders.contentTypeHeader];
  final contentType = header?.firstOrNull?.toLowerCase();
  final isJsonType = contentType?.contains('json') ?? false;
  if (isJsonType) context['json'] = jsonDecode(body);
}
